package com.zihan.utils;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.zihan.domain.entity.ActivityParticipant;
import com.zihan.domain.vo.ActivityVO;
import com.zihan.mapper.ActivityMapper;
import com.zihan.service.SimplePdfCertificateService;
import com.zihan.service.IActivityParticipantService;
import com.zihan.service.IActivityService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    @Resource
    private IActivityService activityService;
    @Resource
    private ActivityMapper activityMapper;
    @Resource
    private SimplePdfCertificateService generatorService;
    @Resource
    private IActivityParticipantService activityParticipantService;


    public AliOssUtil(String endpoint, String accessKeyId, String accessKeySecret, String bucketName) {
        this.endpoint = endpoint;
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.bucketName = bucketName;
    }

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());
        return stringBuilder.toString();
    }


    /**
     * 上传文件到阿里云 OSS
     *
     * @param inputStream      文件输入流
     * @param originalFilename 原始文件名（例如 test.pdf / demo.docx）
     * @return 文件在 OSS 上的访问 URL
     */
    public String upload(InputStream inputStream, String originalFilename) {
        // 创建 OSS 客户端
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 判断文件类型，只允许 pdf/doc/docx
            if (!originalFilename.matches(".*\\.(pdf|doc|docx|xlsx|zip)$")) {
                throw new IllegalArgumentException("只允许上传 PDF 或 Word 文件或者zip！");
            }
            // 生成文件名
            String datePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            String fileName = IdUtil.randomUUID() + "/" + originalFilename;
            String objectName = "uploads/" + datePath + "/" + fileName;
            // 上传文件到 OSS
            ossClient.putObject(bucketName, objectName, inputStream);
            StringBuilder stringBuilder = new StringBuilder("https://");
            stringBuilder
                    .append(bucketName)
                    .append(".")
                    .append(endpoint)
                    .append("/")
                    .append(objectName);
            log.info("文件上传到:{}", stringBuilder.toString());
            return stringBuilder.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传失败：" + e.getMessage());
        } finally {
            // 关闭 OSS 客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    public void generateAndUpload(Long activityId) {
        List<ActivityVO> activities = activityMapper.getInfoOfCertificates(activityId);

        if (activities == null || activities.isEmpty()) {
            log.warn("未找到活动 {} 的参与者信息", activityId);
            return;
        }
        List<ActivityParticipant> participants = new ArrayList<>(activities.size());
        for (ActivityVO activity : activities) {
            try {
                String username = activity.getUsername();
                String activityName = activity.getTitle();
                //  生成 PDF 证书
                File pdfFile = generatorService.generatePdf(username, activityName);
                String originalFilename = username + "-" + activityName + ".pdf";
                //  上传到 OSS
                try (InputStream inputStream = new FileInputStream(pdfFile)) {
                    String fileUrl = upload(inputStream, originalFilename);
                    log.info("证书上传成功：{}", fileUrl);
                    // 保存证书到 数据库
                    ActivityParticipant activityParticipant = new ActivityParticipant()
                            .setActivityId(activityId)
                            .setUserId(activity.getUserId())
                            .setId(activity.getId())
                            .setCertificateUrl(fileUrl)
                            .setCertificateCode(UUID.fastUUID().toString());
                    participants.add(activityParticipant);
                }
                // 删除临时文件
                if (pdfFile.exists()) {
                    pdfFile.delete();
                }
                log.info("证书生成成功：{}", activity.getUsername());
            } catch (Exception e) {
                log.error("生成或上传证书失败: {}", e.getMessage(), e);
                throw new RuntimeException("生成证书失败：" + e.getMessage());
            }
        }
        
        // 批量更新所有证书记录
        if (!participants.isEmpty()) {
            activityParticipantService.updateBatchById(participants);
            log.info("批量更新证书记录成功，共 {} 条", participants.size());
        }
    }
}
